﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

using invrt;
using Pibby.Core.IO;
using Pibby.Core.Logging;
using Pibby.Core.Feeds;
using Pibby.Core.Web;

namespace Pibby.Core.Presenters
{
	public static class BackgroundMethods
	{
		public static void DownloadRssFeeds (BackgroundWorker worker, DownloadFilesArgs args)
		{
			if (worker == null)
				return;

			using (IDownloadingService downloader = InversionOfController.Factory.CreateTypeOf<IDownloadingService>())
			{
				downloader.Async = false;

				int item = 0;
				int totalDownloads = args.Downloads.Count;

				foreach (IDownloadable resource in args.Downloads)
				{
					if (worker.CancellationPending)
					{
						return;
					}

					try
					{
						byte[] bytes = downloader.DownloadData(resource.Uri.AbsoluteUri);

						if (resource.Tag != null && bytes != null)
						{
							var inMemory = resource.Tag as IInMemoryDownload;

							if (inMemory != null)
								inMemory.Content = Encoding.UTF8.GetString(bytes);
						}

						worker.ReportProgress(0, new ProgressEventArgs(++item, 
																		totalDownloads, 
																		ProgressEventStatus.Complete,
																		resource.Tag));
					}
					catch (System.Net.WebException ex)
					{
						// need to report exception somehow...
						worker.ReportProgress(0, new ProgressEventArgs(++item, 
																		totalDownloads, 
																		ProgressEventStatus.Error,
																		resource.Tag));

						Logging.Log.Error("Error updating feed " + resource.Uri.AbsoluteUri + " " + ex.Message);

						continue;
					}
				}
			}
		}

		public static void DownloadFiles(BackgroundWorker worker, DownloadFilesArgs args)
		{
			if (worker == null)
				return;

			using (IDownloadingService downloader = InversionOfController.Factory.CreateTypeOf<IDownloadingService>())
			{
				downloader.Async = false;

				int item = 0;
				int totalDownloads = args.Downloads.Count;

				foreach (IDownloadable resource in args.Downloads)
				{
					if (worker.CancellationPending)
					{
						return;
					}

					try
					{
						downloader.Download(resource.Uri.AbsoluteUri, resource.LocalPath);

						if (resource.Tag != null)
						{
							var tag = resource.Tag as IFileDownload;

							if (tag != null)
							{
								//tag.Id = resource. resource.Id;
								tag.SavedTo = resource.LocalPath;
							}
						}

						worker.ReportProgress(0, new ProgressEventArgs(++item, 
																		totalDownloads, 
																		ProgressEventStatus.Complete,
																		resource.Tag));
					}
					catch (System.Net.WebException ex)
					{
						worker.ReportProgress(0, new ProgressEventArgs(++item, 
																		totalDownloads,
																		ProgressEventStatus.Error,
																		resource.Tag));

						Logging.Log.Error("Error updating feed " + resource.Uri.AbsoluteUri + " " + ex.Message);

						continue;
					}
				}
			}
		}


		public static void TransferFiles(BackgroundWorker worker, TransferFilesArgs args)
		{
			if (worker == null)
				return;

			// get the list of files to synch...
			var fileCopier = InversionOfController.Factory.CreateTypeOf<ICopyFiles>();

			int totalFiles = args.Files.Count;

			var recycleBin = InversionOfController.Factory.CreateTypeOf<IRecycleFiles>();
			var factory = InversionOfController.Factory.CreateTypeOf<IFolderFactory>();

			for (int i = 0; i < totalFiles; ++i)
			{
				try
				{
					if (worker.CancellationPending)
					{
						return;
					}

					ITransferable synchFile = args.Files[i];

					string fileId = args.Files[i].Id;

					// copy to media player...
					fileCopier.Copy(synchFile.Source, synchFile.TargetPath);

					if (args.Behaviour == AfterCopyBehaviour.DeleteContent)
					{
						recycleBin.Recycle(synchFile.Source);

						var root = System.IO.Path.GetDirectoryName(synchFile.Source);

						var folder = factory.GetFolder(root);

						if (folder.Exists && folder.GetFiles().Count == 0)
						{
							folder.Delete();
						}
					}

					worker.ReportProgress(i, new ProgressEventArgs(i + 1, 
																	totalFiles,
 																	ProgressEventStatus.Complete,
																	args.Files[i].Tag));
				}
				catch (System.IO.IOException ex)
				{
					worker.ReportProgress(0, new ProgressEventArgs(i + 1, 
																	totalFiles,
																	ProgressEventStatus.Error,
																	args.Files[i].Tag));

					Logging.Log.Error("Error transferring file " + args.Files[i].Source + " " + ex.Message);

					continue;
				}
			}

		}

		public static void CleanupFolder(BackgroundWorker worker, CleanupFolderArgs args)
		{
			if (worker == null)
				return;

			var folderFactory = InversionOfController.Factory.CreateTypeOf<IFolderFactory>();

			var topLevelFolder = folderFactory.GetFolder(args.Path);

			int i = 0;
			var allFolders = topLevelFolder.GetSubfolders();
			int totalFolders = allFolders.Count;

			foreach (var folder in allFolders)
			{
				try
				{
					if (worker.CancellationPending)
					{
						return;
					}

					if (folder.Exists && folder.GetFiles().Count == 0)
					{
						folder.Delete();
					}

					worker.ReportProgress(i, new ProgressEventArgs(i + 1,
																	totalFolders,
																	ProgressEventStatus.Complete,
																	null));
				}
				catch (System.IO.IOException)
				{
					worker.ReportProgress(0, new ProgressEventArgs(i + 1,
																	totalFolders,
																	ProgressEventStatus.Error,
																	null));

					continue;
				}

				++i;
			}

		}

	}
}
